package com.itheima.app.mapper;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.Log;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.service.mongo.LocationService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import com.itheima.vo.UserInfoVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service//使用的是spring的
public class UserManager {

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Reference//使用dubbo的,远程调用
    private UserService userService;

    @Reference
    private LocationService locationService;

    @Reference
    private UserInfoService userInfoService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    //用户保存,返回主键
    public Long save(User user) {
        //1. 密码加密
        user.setPassword(SecureUtil.md5(user.getPassword()));

        //2. 保存user,返回主键
        return userService.save(user);
    }

    //根据手机号查询用户
    public User findByPhone(String phone) {
        return userService.findByPhone(phone);
    }

    //发送手机验证码
    public void sendSmsCode(String phone) {
        //1. 生成验证码
        //String code = RandomUtil.randomNumbers(6);

        //2. 发送验证码
        //smsTemplate.sendSms(phone, code);

        //todo 模拟一个验证码
        String code = "123456";

        //3. 保存验证码到redis (有效时间为10分钟)
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + phone, code, Duration.ofMinutes(10));
    }

    //登录注册
    public Map loginRegister(String phone, String verificationCode) {
        //1. 校验验证码,如果校验失败,直接返回错误
        String smsCodeFromRedis = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        if (!StringUtils.equals(verificationCode, smsCodeFromRedis)) {
            throw new RuntimeException("验证码错误!");
        }
        //2. 校验成功之后,先删除redis中的验证码
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE + phone);

        //3. 调用service根据phone查询User
        User user = userService.findByPhone(phone);

        //4. 如果user==null,代表这是新用户在注册,开始注册逻辑
        boolean isNew = false;
        String type="0101";//登录
        if (user == null) {
            //4-1 处理参数
            user = new User();
            user.setPhone(phone);//手机号
            //初始化密码
            user.setPassword(SecureUtil.md5(ConstantUtil.INIT_PASSWORD));
            //4-2 保存用户, 返回主键
            Long id = userService.save(user);
            //4-3 设置对象主键(后面会用到)
            user.setId(id);
            //4-4 设置新用户标识
            isNew = true;

            //4-5向环信中注册
            huanXinTemplate.register(id);

            type="0102";//注册
        }

        //创建日志
        Log log = new Log();
        log.setType(type);//操作类型
        log.setUserId(user.getId());//用户id
        log.setLogTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));//设置日期
        log.setPlace("北京顺义");//位置，mongo中的location中有，从这里面获取
        log.setEquipment("华为19");//设备名称
        rocketMQTemplate.convertAndSend("tanhua-log",log);//发送log



        //5. 创建token
        Map tokenMap = new HashMap<>();
        tokenMap.put("id", user.getId());
        tokenMap.put("phone", user.getPhone());
        String token = JwtUtil.createToken(tokenMap);
        //将token存入redis
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token, JSON.toJSONString(user), Duration.ofDays(7));

        //6. 组装返回值
        Map map = new HashMap();
        map.put("token", token);
        map.put("isNew", isNew);
        return map;
    }

    //保存用户基本信息
    public void saveBaseInfo(UserInfo userInfo) {
        userInfoService.save(userInfo);
    }

    //完善个人的头像信息
    public void savePhotoInfo(Long id, MultipartFile headPhoto) throws IOException {
        //1. 人脸识别,如果失败,直接报错
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        System.out.println("人脸识别结果:" + detect);
        if (!detect) {
            throw new RuntimeException("人脸审核失败");
        }

        //2. 阿里云文件上传,返回访问路径
        String filePath = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        System.out.println("文件上传之后的访问路径是:" + filePath);

        //3. 将访问路径设置userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setId(id);
        userInfo.setCoverPic(filePath);//coverPic：封面
        userInfo.setAvatar(filePath);//avatar：头像

        //4. 调用service更新
        userInfoService.update(userInfo);
    }

    //根据id查询用户信息
    public UserInfoVo findById(Long userID) {
        //调用userInfoService查询用户信息
       UserInfo userInfo = userInfoService.findById(userID);
       //组装返回数据
        UserInfoVo userInfoVo = new UserInfoVo();
        //属性复制,条件是两个对象中的属性完全一样的可以复制
        BeanUtils.copyProperties(userInfo,userInfoVo);
        userInfoVo.setAge(userInfo.getAge()+"");
        return userInfoVo;
    }

    //修改个人信息
    public void updateBaseInfo(UserInfo userInfo) {
        //调用service更新用户信息
        userInfoService.update(userInfo);
    }

    //上报个人位置信息
    public void saveUserLocation(Double latitude, Double longitude, String addr) {
        //获取登录用户id
        Long userId = UserHolder.getUser().getId();

        //调用service上报地理信息
        locationService.saveUserLocation(userId,latitude,longitude,addr);
    }



    //核对验证码
    public boolean checkCode(String phone, String verificationCode) {
        boolean verification=true;
        //1. 校验验证码,如果校验失败,直接返回错误
        String smsCodeFromRedis = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE +phone);
        System.out.println("redis中的验证码："+smsCodeFromRedis);
        if (!StringUtils.equals(verificationCode, smsCodeFromRedis)) {
            verification=false;
            System.out.println(verification);
            throw new RuntimeException("验证码错误!");
        }
        //2. 校验成功之后,先删除redis中的验证码
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE + phone);
        System.out.println(verification);
        return verification;
    }

    //修改手机号
    public void updatePhoneByUserId(String phone) {
        //查询当前用户
        User user = userService.findByPhone(UserHolder.getUser().getPhone());
        user.setPhone(phone);//修改手机号
        userService.update(user);
    }
}
